﻿#include "FITKAbstractStruPostVTK.h"

#include "FITKCutViewManager.h"
#include "FITKStruPostMessageText.h"
#include "FITKStruPostDisplayGroup.h"

#include "FITK_Interface/FITKVTKAlgorithm/FITKDataSetDealer.h"
#include "FITK_Interface/FITKVTKAlgorithm/FITKDeformFilter.h"
#include "FITK_Interface/FITKVTKAlgorithm/FITKHighOrderCellFilter.h"
#include "FITK_Interface/FITKInterfaceMesh/FITKMeshFeatureVTK.h"
#include "FITK_Kernel/FITKAppFramework/FITKAppFramework.h"
#include "FITK_Kernel/FITKAppFramework/FITKAppSettings.h"

#include <vtkDataSet.h>
#include <vtkPointData.h>
#include <vtkCellData.h>
#include <vtkDataArray.h>
#include <vtkSelectionNode.h>
#include <vtkSelection.h>
#include <vtkExtractSelection.h>
#include <vtkIdTypeArray.h>
#include <vtkDataSetReader.h>
#include <vtkCellDataToPointData.h>
#include <vtkUnstructuredGrid.h>
#include <vtkIdFilter.h>

namespace Interface
{

    FITKAbstractStructuralPostVTK::FITKAbstractStructuralPostVTK()
    {
        //创建管线
        _dataSetReader = vtkDataSetReader::New();
        _dataSetReader->SetReadAllVectors(true);
        _dataSetReader->SetReadAllNormals(true);
        _dataSetReader->SetReadAllFields(true);
        _dataSetReader->SetReadAllScalars(true);
        _dataSetReader->SetReadAllColorScalars(true);
        _dataSetReader->SetReadAllTCoords(true);
        _dataSetReader->SetReadAllTensors(true);

        //将单元数据转换为点数据（单元云图需要平滑过渡）<By BaGuiJun>
        vtkSmartPointer<vtkCellDataToPointData> pointToCellAlg = vtkSmartPointer<vtkCellDataToPointData>::New();
        pointToCellAlg->SetInputConnection(_dataSetReader->GetOutputPort());
        // pointToCellAlg->Update();

        // 追加元素ID。
        vtkSmartPointer<vtkIdFilter> idFilter = vtkSmartPointer<vtkIdFilter>::New();
        idFilter->SetCellIds(true);
        idFilter->SetPointIds(false);
        idFilter->SetFieldData(false);
        idFilter->SetPointIdsArrayName(FITKMeshFeatureVTK::GetPointIdArrayName());
        idFilter->SetCellIdsArrayName(FITKMeshFeatureVTK::GetCellIdArrayName());
        idFilter->SetInputConnection(pointToCellAlg->GetOutputPort());

        // 创建读取结果处理器。
        _dataSetDealer = FITKDataSetDealer::New();
        _dataSetDealer->SetInputConnection(idFilter->GetOutputPort());

        // 创建形变过滤器。
        _deformFilter = FITKDeformFilter::New();
        // _deformFilter->SetInputConnection(_dataSetDealer->GetOutputPort());

        // 初始化分组显示数据提取器。
        //@{
        _selectNode = vtkSelectionNode::New();
        _section = vtkSelection::New();
        _extractSelection = vtkExtractSelection::New();
        _selectNode->SetContentType(vtkSelectionNode::INDICES);
        _selectNode->SetFieldType(vtkSelectionNode::SelectionField::CELL);
        _section->AddNode(_selectNode);
        _extractSelection->SetInputData(1, _section);

        _idArray = vtkIdTypeArray::New();
        _selectNode->SetSelectionList(_idArray);
        _extractSelection->SetInputConnection(idFilter->GetOutputPort());
        _deformFilter->SetInputConnection(_extractSelection->GetOutputPort());

        this->setEnableDisplayGroup(false);
        //@}

        // 创建网格特征数据，关闭ID数据生成。
        _feature = new Interface::FITKMeshFeatureVTK(_deformFilter->GetOutputPort());
        _feature->setCellAndPointIdsEnable(false, false);
         
        QString deformVec;
        AppFrame::FITKAppSettings* appSettings = FITKAPP->getAppSettings();
        if (appSettings != nullptr)
        {
            _unDeformFactor = appSettings->getValue<double>("StructualPost/UnDeformFactor");
            deformVec = appSettings->getValue<QString>("StructualPost/DeformVecName");
        }
        QByteArray ba = deformVec.toLocal8Bit();
        _deformFilter->SetDeformArrayName(ba.data());

        this->enableDeform(false);

        //初始化信息文本 <By BaGuiJun>
        _textData = new FITKStruPostMessageText();

        // 初始化显示分组管理器。
        m_displayGroupManager = new FITKPostGroupManager;
    }

    FITKAbstractStructuralPostVTK::~FITKAbstractStructuralPostVTK()
    {
        _dataSetReader->Delete();
        _dataSetDealer->Delete();
        _deformFilter->Delete();

        if (_cutViewManager)
            delete _cutViewManager;

        // 析构分组管理器。
        if (m_displayGroupManager)
        {
            delete m_displayGroupManager;
            m_displayGroupManager = nullptr;
        }

        // 析构数据提取器。
        //@{
        if (_selectNode)
        {
            _selectNode->Delete();
            _selectNode = nullptr;
        }

        if (_section)
        {
            _section->Delete();
            _section = nullptr;
        }

        if (_idArray)
        {
            _idArray->Delete();
            _idArray = nullptr;
        }

        if (_extractSelection)
        {
            _extractSelection->Delete();
            _extractSelection = nullptr;
        }

        if (_textData) {
            delete _textData;
            _textData = nullptr;
        }

        if (_feature)
        {
            delete _feature;
            _feature = nullptr;
        }
    }

    /**
     * @brief 获取结构后处理类型
     *
     * @return StruPostType 返回当前结构后处理的类型。
     */
    StruPostType FITKAbstractStructuralPostVTK::getPostStructualType()
    {
        return SPTNone;
    }

    /**
     * @brief 设置前置案例ID
     *
     * @param id 设置的前置案例的ID。
     */
    void FITKAbstractStructuralPostVTK::setPreCaseID(const int id)
    {
        _preCaseID = id;
    }

    /**
     * @brief 获取前置案例ID
     *
     * @return int 返回当前设置的前置案例的ID。
     */
    int FITKAbstractStructuralPostVTK::getPreCaseID()
    {
        return _preCaseID;
    }

    FITKStruPostMessageText * FITKAbstractStructuralPostVTK::getMessageTextData()
    {
        return _textData;
    }

    void FITKAbstractStructuralPostVTK::updateText()
    {

    }

    void FITKAbstractStructuralPostVTK::setInputFile(const QString & file)
    {
        //更新文件输入
        QByteArray ba = file.toLocal8Bit();
        if (_dataSetReader == nullptr) return;
        _dataSetReader->SetFileName(ba.data());
        if (_dataSetReader == nullptr || _deformFilter == nullptr) return;
        if (_dataSetDealer == nullptr) return;

        // 刷新网格特征提取。
        _dataSetReader->Update();

        _feature->reset(_deformFilter->GetOutputPort());

        //更新文本信息
        updateText();
    }

    QString FITKAbstractStructuralPostVTK::getInputFile()
    {
        if (_dataSetReader == nullptr) return "";
        const char* f = _dataSetReader->GetFileName();
        return QString::fromLocal8Bit(f);
    }

    void FITKAbstractStructuralPostVTK::resetDisplayGroup()
    {
        if (!_idArray || !_dataSetDealer)
        {
            return;
        }

        // 清空分组ID列表。
        _idArray->Reset();
        _idArray->SetNumberOfValues(0);

        // 使用新数据集填充ID。
        _dataSetDealer->Update();
        vtkDataSet* dataSet = _dataSetDealer->GetOutput();
        if (!dataSet)
        {
            return;
        }

        int nCells = dataSet->GetNumberOfCells();
        for (int i = 0; i < nCells; i++)
        {
            _idArray->InsertNextValue(i);
        }

        if (_section)
        {
            _section->Modified();
        }

        if (_extractSelection)
        {
            _extractSelection->Update();
        }
    }

    vtkDataSetReader* FITKAbstractStructuralPostVTK::getDataSetReader()
    {
        return _dataSetReader;
    }

    FITKDeformFilter* FITKAbstractStructuralPostVTK::getDeformFilter()
    {
        return _deformFilter;
    }

    FITKMeshFeatureVTK* FITKAbstractStructuralPostVTK::getMeshFeature()
    {
        return _feature;
    }

    vtkAlgorithm* FITKAbstractStructuralPostVTK::getOutputAlgorithm()
    {
        // 计算管线使用变形算法输出。
        return _deformFilter;
    }

    vtkAlgorithm* FITKAbstractStructuralPostVTK::getRenderOutputAlgorithm()
    {
        // 无网格特征则直接使用变形数据。
        if (!_feature)
        {
            return _deformFilter;
        }

        // 检查是否开启数据提取。
        //if (_idArray)
        //{
        //    if (_idArray->GetNumberOfValues() != 0)
        //    {
        //        return _extractSelection;
        //    }
        //}

        // 获取高阶单元过滤器输出。
        FITKHighOrderCellFilter* filter = _feature->getHighOrderFilter();
        if (filter)
        {
            return filter;
        }

        return _deformFilter;
    }

    vtkExtractSelection* FITKAbstractStructuralPostVTK::getDisplayGroupExtractor()
    {
        return _extractSelection;
    }

    QStringList FITKAbstractStructuralPostVTK::getVariables(VariableLocation loc)
    {
        QStringList variables;
        vtkDataSet* ds = _dataSetDealer->GetOutput();
        if (ds == nullptr) return variables;
        //节点值
        if (loc == VALOCNode)
        {
            vtkPointData* pd = ds->GetPointData();
            if (pd == nullptr) return variables;
            const int na = pd->GetNumberOfArrays();
            //遍历所有变量
            for (int i =0;i<na; ++i)
            {
                QString va = QString(pd->GetArrayName(i));
                variables.append(va);
            }
           
        }
        //单元值
        else if (loc == VALOCEle)
        {
            vtkCellData* cd = ds->GetCellData();
            if (cd == nullptr) return variables;
            const int na = cd->GetNumberOfArrays();
            //遍历所有变量
            for (int i = 0; i < na; ++i)
            {
                QString va = QString(cd->GetArrayName(i));
                variables.append(va);
            }
        }
        return variables;
    }

    QStringList FITKAbstractStructuralPostVTK::getVariableComponents(VariableLocation loc, 
        const QString& variaable)
    {
        QStringList comps;
        vtkDataArray* array = nullptr;
        QByteArray ba = variaable.toLocal8Bit();

        vtkDataSet* ds = _dataSetDealer->GetOutput();
        if (ds == nullptr) return comps;
        //节点值
        if (loc == VALOCNode)
        {
            vtkPointData* pd = ds->GetPointData();
            if (pd == nullptr) return comps;
            array = pd->GetArray(ba.data());
        }
        //单元值
        else if (loc == VALOCEle)
        {
            vtkCellData* cd = ds->GetCellData();
            if (cd == nullptr) return comps;
            array = cd->GetArray(ba.data());
        }
        if (array == nullptr) return comps;
        //变量所有组分
        const int ncp = array->GetNumberOfComponents();
        //只有一个组分，是标量，返回空
        if (ncp == 1) return comps;
        for (int i=0;i<ncp; ++i)
        {
            comps.append(array->GetComponentName(i));
        }
        return comps;
    }

    int FITKAbstractStructuralPostVTK::getNumberOfCells()
    {
        if (!_dataSetReader)
        {
            return 0;
        }

        _dataSetReader->Update();
        vtkDataSet* dataSet = _dataSetReader->GetOutput();
        if (!dataSet)
        {
            return 0;
        }

        return dataSet->GetNumberOfCells();
    }

    void FITKAbstractStructuralPostVTK::nextFrame()
    {

    }

    void FITKAbstractStructuralPostVTK::previousFrame()
    {

    }

    void FITKAbstractStructuralPostVTK::firstFrame()
    {

    }

    void FITKAbstractStructuralPostVTK::lastFrame()
    {

    }

  
    void FITKAbstractStructuralPostVTK::enableDeform(bool enable)
    {
        double factor = _unDeformFactor;
        _enableDeform = enable;
        //变形为不变形与变形系数的和
        if (_enableDeform )
            factor += _deformFactor;

        if (_deformFilter)
        {
            _deformFilter->SetScaleFactor(factor);
            _deformFilter->Update();
        }
        _enableDeform = enable;
    }

    void FITKAbstractStructuralPostVTK::setDeformFactor(const double fac)
    {
        _deformFactor = fac;
        if (_enableDeform && _deformFilter)
        {
            double cd = _deformFilter->GetScaleFactor();
            double d = _unDeformFactor + _deformFactor;
            //变形一致，不进行更新操作
            if (fabs(d - cd) < 1e-9) return;
            _deformFilter->SetScaleFactor(d);
            _deformFilter->Update();
        }
    }

    double FITKAbstractStructuralPostVTK::getDeformFactor()
    {
        return _deformFactor;
    }

    void FITKAbstractStructuralPostVTK::setUnDeformFactor(const double fac)
    {
        _unDeformFactor = fac;
    }

    double FITKAbstractStructuralPostVTK::getUnDeformFactor()
    {
        return _unDeformFactor;
    }

    void FITKAbstractStructuralPostVTK::setDeformVariable(const QString& va)
    {
        if (_deformFilter == nullptr) return;
        //变量相同不进行操作
        QString cv = this->getDeformVariable();
        if (cv == va) return;
        QByteArray ba = va.toLocal8Bit();
        _deformFilter->SetDeformArrayName(ba.data());
        _deformFilter->Update();
    }

    QString FITKAbstractStructuralPostVTK::getDeformVariable()
    {
        return QString::fromLocal8Bit(_deformFilter->GetDeformArrayName());
    }

    Interface::FITKCutViewManager* FITKAbstractStructuralPostVTK::getCutViewManager()
    {
        if (_cutViewManager == nullptr)
            _cutViewManager = new FITKCutViewManager(this);
        return _cutViewManager;
    }

    void FITKAbstractStructuralPostVTK::setShowCutWidget(bool visible)
    {
        _cutWidgetVisible = visible;
    }

    bool FITKAbstractStructuralPostVTK::getShowCutWidget()
    {
        return _cutWidgetVisible;
    }

    void FITKAbstractStructuralPostVTK::setShowViewCut(bool flag)
    {
        _cutViewVisible = flag;
    }

    bool FITKAbstractStructuralPostVTK::getShowViewCut()
    {
        return _cutViewVisible;
    }

    void FITKAbstractStructuralPostVTK::setEnableDisplayGroup(bool flag)
    {
        _enableDisplayGroup = flag;
    }

    bool FITKAbstractStructuralPostVTK::getEnableDisplayGroup()
    {
        return _enableDisplayGroup;
    }

    void FITKAbstractStructuralPostVTK::setDisplayGroupEleIndice(QList<int> indice)
    {
        if (!_idArray)
        {
            _enableDisplayGroup = false;
            return;
        }

        if (indice.count() == 0)
        {
            // 重置索引。
            resetDisplayGroup();
        }
        else
        {
            // 填充数据提取数组。
            _idArray->Reset();
            _idArray->SetNumberOfValues(0);

            for (const int & index : indice)
            {
                _idArray->InsertNextValue(index);
            }

            if (indice.count() == 0)
            {
                _enableDisplayGroup = false;
            }
        }

        _selectNode->Modified();
    }

    QList<int> FITKAbstractStructuralPostVTK::getDisplayGroupEleIndice()
    {
        QList<int> indice;
        if (!_idArray)
        {
            return indice;
        }

        for (int i = 0; i < _idArray->GetNumberOfValues(); i++)
        {
            indice.push_back(_idArray->GetValue(i));
        }

        return indice;
    }

    int FITKAbstractStructuralPostVTK::getNumberOfDisplayGroupMember()
    {
        if (!_idArray)
        {
            return 0;
        }

        return _idArray->GetNumberOfValues();
    }

    QString FITKAbstractStructuralPostVTK::getDisplayGroupName()
    {
        return _groupName;
    }

    FITKPostGroupManager* FITKAbstractStructuralPostVTK::getDisplayGroupManager()
    {
        return m_displayGroupManager;
    }

    void FITKAbstractStructuralPostVTK::setDisplayGroupName(QString name)
    {
        _groupName = name;
    }
}
